<!-- 生成问卷suveryjs公用组件 -->
<template>
  <div>
    <div id="surveyCreator" />
    <t-dialog
      ref="dialog"
      width="600px"
      top="48px"
      :visible.sync="dialogVisible"
      :closeOnOverlayClick="false"
      @confirm="handleOnConfirm(formData)"
      @closed="handleOnClose"
    >
      <t-form ref="form" class="risk-form" :data="formData" :rules="FORM_RULES" label-align="top">
        <t-space direction="vertical" style="width: 100%">
          <t-form-item label="逻辑类型" name="logicType">
            <t-select
              v-model="formData.logicType"
              :options="logicTypeOptions"
              placeholder="请选择逻辑类型"
              @change="selectChangeHandle"
            />
          </t-form-item>
          <template
            v-if="
              [
                LOGIC_TYPE_STATUS.EQUALS,
                LOGIC_TYPE_STATUS.DOES_NOT_EQUALS,
                LOGIC_TYPE_STATUS.ANY_OF,
                LOGIC_TYPE_STATUS.ALL_OF,
              ].includes(formData.logicType)
            "
          >
            <t-form-item :label="questionTitle" name="logic">
              <t-checkbox-group
                v-if="this.questionType === 'listbox'"
                v-model="formData.logic"
                :options="questionValue"
                @change="checkboxChangeHandle"
              />
              <t-radio-group
                v-if="this.questionType === 'radiogroup'"
                v-model="formData.logic"
                :options="questionValue"
              />
              <t-radio-group v-if="this.questionType === 'textbox'" v-model="formData.logic" :options="questionValue" />
            </t-form-item>
          </template>
          <template
            v-if="[LOGIC_TYPE_STATUS.CONTAINS, LOGIC_TYPE_STATUS.DOES_NOT_CONTAINS].includes(formData.logicType)"
          >
            <t-form-item :label="questionTitle" name="logic">
              <t-radio-group v-model="formData.logic" :options="anyofQuestionValue" />
            </t-form-item>
          </template>
          <!-- <template
            v-if="[LOGIC_TYPE_STATUS.CONTAINS, LOGIC_TYPE_STATUS.DOES_NOT_CONTAINS].includes(formData.logicType)"
          >
            <t-form-item label="逻辑设置（此次风险所对应的文本内容）" name="logic">
              <t-input v-model="formData.logic" />
            </t-form-item>
          </template> -->
          <div class="risk-discovery">
            <span class="title">评审结果：</span>
            <div class="risk-box">
              <div
                class="risk-box__item"
                :class="{ red: ![RISK_STATUS.NO, RISK_STATUS.TO_BE_CONFIRMED].includes(formData.level) }"
                @click="formData.level = RISK_STATUS.LOW"
              >
                发现风险
              </div>
              <div
                class="risk-box__item"
                :class="{ green: formData.level === RISK_STATUS.NO }"
                @click="formData.level = RISK_STATUS.NO"
              >
                未发现风险
              </div>
              <div
                class="risk-box__item"
                :class="{ blue: formData.level === RISK_STATUS.TO_BE_CONFIRMED }"
                @click="formData.level = RISK_STATUS.TO_BE_CONFIRMED"
              >
                不确定
              </div>
            </div>
          </div>
          <template v-if="formData.level && ![RISK_STATUS.NO, RISK_STATUS.TO_BE_CONFIRMED].includes(formData.level)">
            <t-form-item label="风险等级" name="level">
              <t-radio-group class="level" v-model="formData.level" variant="primary-filled">
                <t-radio-button
                  v-for="(item, key) in filterRiskOptions"
                  :key="key"
                  :value="Number(key)"
                  :style="{ background: formData.level === Number(key) ? item.backgroundColor : '#c5c5c5' }"
                >
                  {{ item.label }}
                </t-radio-button>
              </t-radio-group>
            </t-form-item>
            <t-row :gutter="16">
              <t-col :span="6">
                <t-form-item label="风险类型" name="type">
                  <t-select
                    v-model="formData.type"
                    creatable
                    filterable
                    multiple
                    placeholder="请选择风险类型"
                    :options="typeOptions"
                  />
                </t-form-item>
              </t-col>
              <t-col :span="6">
                <t-form-item label="标签" name="label">
                  <t-select
                    v-model="formData.label"
                    creatable
                    filterable
                    multiple
                    placeholder="请选择风险标签"
                    :options="labelOptions"
                  />
                </t-form-item>
              </t-col>
            </t-row>
            <t-form-item label="风险描述" name="description">
              <t-textarea v-model="formData.description" placeholder="请输入风险描述" autosize />
            </t-form-item>
            <t-form-item label="法律依据" name="law">
              <t-textarea v-model="formData.law" placeholder="请输入内容" autosize />
            </t-form-item>
            <t-form-item label="标准依据" name="standard">
              <t-textarea v-model="formData.standard" placeholder="请输入内容" autosize />
            </t-form-item>
            <t-form-item label="合规参考案例" name="compliance">
              <t-textarea v-model="formData.compliance" placeholder="请输入内容" autosize />
            </t-form-item>
            <t-form-item label="添加附件" name="file">
              <upload v-model="files" />
            </t-form-item>
          </template>
        </t-space>
      </t-form>
      <template #header>
        <template v-if="isEditRiskName">
          <t-input v-model="formData.name" @blur="isEditRiskName = false" placeholder="请输入风险名称">
            <template #suffix>
              <check-icon @click="isEditRiskName = false" size="16" style="cursor: pointer" />
            </template>
          </t-input>
        </template>
        <template v-else>
          <span>{{ formData.name }}</span>
          <edit1-icon
            @click="isEditRiskName = true"
            size="16"
            style="position: relative; left: 10px; top: 5px; cursor: pointer"
          />
        </template>
      </template>
    </t-dialog>
  </div>
</template>

<script lang="jsx">
import * as ko from 'knockout';
import SurveyLanguageCn from '@/constants/survey-language-cn';
import { SurveyCreator } from 'survey-creator-knockout';
import { localization, PropertyGridEditorCollection } from 'survey-creator-core';
import { Serializer, RendererFactory, QuestionPanelDynamicItem } from 'survey-core';
import 'survey-core/defaultV2.min.css';
import 'survey-creator-core/survey-creator-core.min.css';

import Upload from '@/components/Upload/index.vue';
import { DialogPlugin } from 'tdesign-vue';
import { Edit1Icon, CheckIcon } from 'tdesign-icons-vue';
import {
  riskOptions,
  filterRiskOptions,
  typeOptions,
  labelOptions,
  RISK_STATUS,
  LOGIC_TYPE_STATUS,
} from '@/constants/risk-assessment-template';
import { FILE_URL_PREFIX } from '@/constants/index';

// 设置中文语言包
// const deuLocale = localization.getLocale('zh-cn')
localization.locales['zh-cn'] = SurveyLanguageCn;
// deuLocale.ed.addNewQuestion = '新问题'
// deuLocale.ed.addNewTypeQuestion = '添加 {0}'
localization.currentLocale = 'zh-cn';

// 为这几种问题类型添加风险工具栏
Serializer.addProperty('checkbox', {
  name: '设置风险',
  type: 'risk',
  category: '风险',
  categoryIndex: 10,
  visibleIf: (obj) => {
    const parentIsDynamicPanel = obj.parent?.isPanel && obj.parent?.data instanceof QuestionPanelDynamicItem;
    return !parentIsDynamicPanel;
  },
});
Serializer.addProperty('boolean', {
  name: '设置风险',
  type: 'risk',
  category: '风险',
  categoryIndex: 10,
  visibleIf: (obj) => {
    const parentIsDynamicPanel = obj.parent?.isPanel && obj.parent?.data instanceof QuestionPanelDynamicItem;
    return !parentIsDynamicPanel;
  },
});
Serializer.addProperty('radiogroup', {
  name: '设置风险',
  type: 'risk',
  category: '风险',
  categoryIndex: 10,
  visibleIf: (obj) => {
    const parentIsDynamicPanel = obj.parent?.isPanel && obj.parent?.data instanceof QuestionPanelDynamicItem;
    return !parentIsDynamicPanel;
  },
});
PropertyGridEditorCollection.register({
  fit(prop) {
    return prop.type === 'risk';
  },
  getJSON() {
    return {
      type: 'dropdown',
      renderAs: 'dropdown-vue',
    };
  },
});

const creator = new SurveyCreator({
  // 指定用户是否可以在“预览”选项卡中的 UI 主题之间切换。
  allowChangeThemeInPreview: true,
  // 指定用户是否可以将“逻辑”选项卡中的表达式编辑为纯文本。
  // 如果将此属性设置为false，则用户只能使用 UI 元素来编辑逻辑表达式。
  allowEditExpressionsInTextEditor: true,
  // 指定用户是否可以添加、编辑和删除调查页面。
  allowModifyPages: true,
  // 指定 Survey Creator 是将调查定义生成为有效的 JSON 对象(true)还是 JavaScript 对象(false)。
  generateValidJSON: true,
  // 删除免费试用栏。只有拥有 Survey Creator 商业许可证才能启用此属性。未经许可启用此属性是非法的。
  haveCommercialLicense: true,
  // 指定每次更改调查设置时是否调用saveSurveyFunc 。
  isAutoSave: true,
  // 指定是否启用对从右到左的语言的支持。
  isRTL: false,
  // 限制用户可以添加到Checkbox、Dropdown和Radiogroup问题的选项数量。默认值：0（无限制）
  maximumChoicesCount: 0,
  // 限制用户可以添加到Matrix、Matrix Dynamic和Matrix Dropdown问题的列数。
  maximumColumnsCount: 0,
  // 限制用户可以添加到评级问题的评级值的数量。
  maximumRateValues: 0,
  // 限制用户可以添加到Matrix和Matrix Dropdown问题的行数。
  maximumRowsCount: 0,
  // 限制逻辑表达式中的项目数。默认值：-1（无限制）
  maxLogicItemsInCondition: -1,
  // 限制可见选择的数量。用户可以点击“显示更多”来查看隐藏的选项。
  // 如果不想隐藏任何选项，请将此属性设置为 -1。
  maxVisibleChoices: 10,
  // 指定 Survey Creator 用户如何编辑调查页面。
  // 接受的值：
  // "standard"（默认）
  // 问题和面板在页面之间划分。用户可以滚动设计表面以到达所需的页面。
  // "single"
  // 所有问题和面板都属于一个页面。用户不能添加或删除页面。
  // "bypage"
  // 问题和面板在页面之间划分。用户可以使用页面导航器切换到所需的页面。
  pageEditMode: 'standard',
  // 在“预览”选项卡中指定所选设备的方向。
  // 可能的值：
  // "landscape"（默认）
  // "portrait"
  previewOrientation: 'landscape',
  // questionTypes 限制工具箱和添加问题菜单中可用的问题和面板类型。
  questionTypes: [
    'radiogroup',
    'checkbox',
    'boolean',
    'file',
    'text',
    'comment',
    'multipletext',
    'panel',
    'matrix',
    'matrixdropdown',
    'matrixdynamic',
    'paneldynamic',
  ],
  // 启用只读模式。如果将此属性设置为true，则用户无法更改初始调查配置。
  readOnly: false,
  // 指定预览选项卡是否显示语言选择器。
  // 接受的值：
  // "auto"（默认）
  // 仅当调查被翻译成多种语言时才显示语言选择器。
  // true
  // 无论调查中使用了多少种语言，始终显示语言选择器。
  // false
  // 从不显示语言选择器。
  // "all"
  // 始终显示包含所有受支持语言的语言选择器。
  showDefaultLanguageInPreviewTab: 'auto',
  // 指定是否显示设计器选项卡。
  showDesignerTab: true,
  // 指定是否显示嵌入调查选项卡。
  showEmbeddedSurveyTab: false,
  // 指定如果调查未保存在数据库中是否显示错误消息。
  showErrorOnFailedSave: true,
  // 指定当调查不包含任何元素时设计图面是否显示调查标题和描述。
  showHeaderInEmptySurvey: false,
  // 指定“预览”选项卡是否显示允许用户显示或隐藏不可见调查元素的复选框。
  showInvisibleElementsInPreviewTab: true,
  // 指定是否显示 JSON 编辑器选项卡。
  showJSONEditorTab: false,
  // 指定是否显示逻辑选项卡。
  showLogicTab: true,
  // 指定 UI 元素是否显示调查、页面和问题标题而不是它们的名称。
  showObjectTitles: false,
  // 指定是否在“预览”选项卡底部显示页面选择器。
  showPagesInPreviewTab: true,
  // 指定是否显示预览选项卡。
  showPreviewTab: true,
  // 指定预览选项卡是否显示允许用户在不同设备类型上预览调查的设备按钮。
  showSimulatorInPreviewTab: true,
  // 指定用户是否可以查看和编辑调查标题和相关调查属性。
  showSurveyTitle: true,
  // 指定当用户编辑逻辑表达式时是否显示问题标题而不是名称。
  showTitlesInExpressions: false,
  // 指定是否显示翻译选项卡。
  showTranslationTab: false,
  // 用于在“预览”选项卡中显示调查的UI 主题。
  // 可接受的值："modern", "default","defaultV2"
  // 默认值："defaultV2"
  themeForPreview: 'defaultV2',
});
// 更改添加问题工具栏的分类
// creator.toolbox.changeCategories([
//   { name: 'panel', category: 'Panels' },
//   { name: 'radiogroup', category: 'Panels' },
//   { name: 'multipletext', category: 'Panels' },
//   { name: 'boolean', category: 'Panels' },
//   { name: 'file', category: 'Panels' },
//   { name: 'checkbox', category: 'Panels' },
//   { name: 'singleinput', category: 'Panels' },
//   { name: 'checkbox', category: 'Panels' },
// ]);

export default {
  name: 'surveyCreator',
  components: { Edit1Icon, CheckIcon, Upload },
  props: {
    // surveyjs json字符串
    value: {
      type: String,
      default: '{}',
    },
    // 风险对象
    // risk: {
    //   问题name: [
    //     { 风险名称, 风险等级, 风险描述, 风险逻辑 },
    //     { 风险名称, 风险等级, 风险描述, 风险逻辑 },
    //     { 风险名称, 风险等级, 风险描述, 风险逻辑 },
    //   ]
    // }
    risk: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      // 风险状态 1:无风险 2:低风险 3:中风险 4:高风险 5:严重风险
      RISK_STATUS,
      // 逻辑类型
      // EQUALS: 1,
      // DOES_NOT_EQUALS: 2,
      // CONTAINS: 3,
      // DOES_NOT_CONTAINS: 4,
      // ANY_OF: 5,
      // ALL_OF: 6,
      // EMPTY: 7,
      // NOT_EMPTY: 8,
      LOGIC_TYPE_STATUS,
      // 风险选择选项
      riskOptions,
      filterRiskOptions,
      // 表单数据
      formData: {
        logic: undefined,
        logicType: LOGIC_TYPE_STATUS.EQUALS,
        name: '风险名称',
        description: '',
        level: RISK_STATUS.NO,
        law: '',
        standard: '',
        compliance: '',
        file: '',
        type: [],
        label: [],
      },
      // 风险附件文件列表
      files: [],
      // 风险类型列表
      typeOptions,
      // 风险标签列表
      labelOptions,
      // 是否正在编辑风险名称
      isEditRiskName: false,
      // 当前修改的风险在数组中的下标
      editIndex: -1,
      // dialog是否展示
      dialogVisible: false,
      // 当前问题title
      questionTitle: '',
      // 当前问题name，唯一
      questionName: '',
      // 当前问题的选项数组
      questionValue: [],
      // 当前问题类型
      questionType: '',
    };
  },
  computed: {
    // 当前风险问题的逻辑数组
    riskLogicArr() {
      return this.risk[this.questionName]?.map((i) => {
        const type = i.logicType ? `${i.logicType}-` : '';
        const logic = Array.isArray(i.logic) ? i.logic.toString() : `${i.logic}`;
        return type + logic;
      });
    },
    // 是否存在当前选择的逻辑用于表单校验
    isExistLogic() {
      const type = this.formData.logicType ? `${this.formData.logicType}-` : '';
      const logic = Array.isArray(this.formData.logic)
        ? this.formData.logic.filter((i) => i !== 'all').toString()
        : `${this.formData.logic}`;
      const currentLogic = type + logic;
      // 当前若正在修改风险，当前逻辑与修改前逻辑相同时不校验表单
      if (this.editIndex > -1) {
        const riskData = this.risk[this.questionName][this.editIndex];
        const _type = riskData.logicType ? `${riskData.logicType}-` : '';
        const _logic = Array.isArray(riskData.logic) ? riskData.logic.toString() : `${riskData.logic}`;
        const editLogic = _type + _logic;
        if (currentLogic === editLogic) return false;
      }
      // 判断逻辑数组是否包含当前逻辑
      return this.riskLogicArr?.includes(currentLogic);
    },
    // 表单校验规则
    FORM_RULES() {
      return {
        logic: [{ required: true, message: '请设定风险逻辑', type: 'error' }],
        level: [{ required: true, message: '请设定风险等级', type: 'error' }],
        description: [{ required: true, message: '请输入风险描述', type: 'error' }],
        logicType: [
          { required: true, message: '请选择逻辑类型', type: 'error' },
          { validator: () => !this.isExistLogic, message: '此风险逻辑已存在', type: 'error' },
        ],
        // type: [{ required: true, message: '请选择风险类型', type: 'error' }],
        // label: [{ required: true, message: '请选择风险标签', type: 'error' }],
        // law: [{ required: true, message: '请输入法律依据', type: 'error' }],
        // standard: [{ required: true, message: '请输入标准依据', type: 'error' }],
        // compliance: [{ required: true, message: '请输入合规案例参考', type: 'error' }],
      };
    },
    // 逻辑类型选择选项
    logicTypeOptions() {
      if (
        this.questionType === 'listbox' ||
        (this.questionType === 'radiogroup' && this.formData.logicType === LOGIC_TYPE_STATUS.ANY_OF)
      ) {
        return [
          { label: '相等的', value: LOGIC_TYPE_STATUS.EQUALS },
          { label: '不相等', value: LOGIC_TYPE_STATUS.DOES_NOT_EQUALS },
          { label: '包含', value: LOGIC_TYPE_STATUS.CONTAINS },
          { label: '不包含', value: LOGIC_TYPE_STATUS.DOES_NOT_CONTAINS },
          { label: '任意一个', value: LOGIC_TYPE_STATUS.ANY_OF },
          { label: '所有的', value: LOGIC_TYPE_STATUS.ALL_OF },
          { label: '空的', value: LOGIC_TYPE_STATUS.EMPTY },
          { label: '非空的', value: LOGIC_TYPE_STATUS.NOT_EMPTY },
        ];
      }
      return [
        { label: '相等的', value: LOGIC_TYPE_STATUS.EQUALS },
        { label: '不相等', value: LOGIC_TYPE_STATUS.DOES_NOT_EQUALS },
        { label: '空的', value: LOGIC_TYPE_STATUS.EMPTY },
        { label: '非空的', value: LOGIC_TYPE_STATUS.NOT_EMPTY },
      ];
    },
    // 逻辑类型为任意一个的可选项
    anyofQuestionValue() {
      return this.questionValue.filter((i) => i.value !== 'all');
    },
  },
  mounted() {
    window.handleOnAdd = this.handleOnAdd;
    window.handleOnDelete = this.handleOnDelete;
    window.handleOnEdit = this.handleOnEdit;
    this.surveyInit();
  },
  beforeDestroy() {
    this.surveyDestroy();
  },
  methods: {
    // 组件初始化
    surveyInit() {
      // 注册模板
      ko.components.register('svc-tab-template', {
        viewModel: {
          createViewModel: () => {
            document.querySelector('.spg-row__question[data-name="设置风险"]').style.position = 'relative';
            this.renderTable();
            let i = 0;
            const model = {
              load: () => {
                if (i > 0) {
                  this.handleOnAdd();
                }
                i += 1;
              },
            };
            return model;
          },
        },
        template: `
          <button class="spg-action-button spg-action-button--icon" style="position: absolute; top: 0; right: 0;" type="button" data-bind="click:load()">
            <svg class="sv-svg-icon spg-action-button__icon" aria-label="添加一个选项" style="width: 24px; height: 24px;">
              <use xlink:href="#icon-add"></use>
              <title>添加一个选项</title>
            </svg>
          </button>
          <table class="spg-table spg-matrixdynamic">
            <tbody class="risk-tbody" style="position: relative;">
            </tbody>
          </table>
            `,
      });
      RendererFactory.Instance.registerRenderer('dropdown', 'dropdown-vue', 'svc-tab-template');
      // surveyjs 监听元素创建的方法
      creator.onPropertyGridSurveyCreated.add((sender, options) => {
        const question = options.obj;
        if (!question.isQuestion) return;

        // 存在是非题的处理逻辑
        if (question.ariaRole === 'textbox' && question.labelTrue) {
          if (question.labelTrue === 'Yes' && question.labelFalse === 'No') {
            question.valueTrue = 'no';
            question.labelTrue = '否';
            question.valueFalse = 'yes';
            question.labelFalse = '是';
          }
          this.questionValue = [
            { value: question.valueFalse ?? false, label: question.labelFalse },
            { value: question.valueTrue ?? true, label: question.labelTrue },
          ];
        }

        // 存在选择框的处理逻辑
        if (question.choices) {
          this.questionValue = question.choices.map((i) => ({ value: i.value, label: i.text }));
          if (question.hasSelectAll) this.questionValue.push({ value: 'all', label: question.selectAllText });
          if (question.hasNone) this.questionValue.push({ value: 'none', label: question.noneText });
          if (question.hasOther) this.questionValue.push({ value: 'other', label: question.otherText });
        }

        this.questionTitle = question.title;
        this.questionName = question.name;
        this.questionType = question.ariaRole;
        if (!this.risk[this.questionName]) this.$set(this.risk, this.questionName, []);
      });
      // surveyjs 监听属性改变的方法
      creator.onSurveyPropertyValueChanged.add((sender, options) => {
        if (options.obj.locOwner?.isQuestion) {
          const question = options.obj.locOwner;
          if (question.ariaRole === 'textbox' && question.labelTrue) {
            this.questionValue = [
              { value: question.valueFalse ?? false, label: question.labelFalse },
              { value: question.valueTrue ?? true, label: question.labelTrue },
            ];
          }
          if (question.choices) {
            this.questionValue = question.choices.map((i) => ({ value: i.value, label: i.text }));
            if (question.hasSelectAll) this.questionValue.push({ value: 'all', label: question.selectAllText });
            if (question.hasNone) this.questionValue.push({ value: 'none', label: question.noneText });
            if (question.hasOther) this.questionValue.push({ value: 'other', label: question.otherText });
          }
        }
        if (options.obj.isQuestion) {
          const question = options.obj;
          if (question.ariaRole === 'textbox' && question.labelTrue) {
            this.questionValue = [
              { value: question.valueFalse ?? false, label: question.labelFalse },
              { value: question.valueTrue ?? true, label: question.labelTrue },
            ];
          }
          if (question.choices) {
            this.questionValue = question.choices.map((i) => ({ value: i.value, label: i.text }));
            if (question.hasSelectAll) this.questionValue.push({ value: 'all', label: question.selectAllText });
            if (question.hasNone) this.questionValue.push({ value: 'none', label: question.noneText });
            if (question.hasOther) this.questionValue.push({ value: 'other', label: question.otherText });
          }
        }
        if (options.name === 'choices' && options.newValue.length === 0) {
          const name = options.oldValue[0]?.value;
          const questionName = options.oldValue[0]?.locOwner.name;
          // eslint-disable-next-line vue/no-mutating-props
          this.risk[questionName] = this.risk[questionName]?.filter((item) =>
            Array.isArray(item.logic) ? !item.logic.includes(name) : name !== item.logic,
          );
          this.renderTable();
        }
        if (options.name === 'elements' && options.newValue.length === 0) {
          this.$set(this.risk, options.oldValue[0].name, []);
          this.renderTable();
        }
      });
      // surveyjs 监听元素删除的方法
      creator.onElementDeleting.add((sender, options) => {
        if (options.element.isQuestion && this.risk[options.element.name]) delete this.risk[options.element.name];
        if (options.element.isPage || options.element.isPanel) {
          options.element.elementsValue.forEach((element) => {
            if (element.isQuestion && this.risk[element.name]) delete this.risk[element.name];
            if (element.isPanel) {
              element.elementsValue.forEach((panel_element) => {
                if (this.risk[panel_element.name]) delete this.risk[panel_element.name];
              });
            }
          });
        }
      });
      // surveyjs json值改变时更新值
      creator.saveSurveyFunc = (saveNo, callback) => {
        this.$emit('input', creator.text);
        callback(saveNo, true);
      };
      creator.text = this.value;
      creator.showToolbox = true;
      creator.render('surveyCreator');
    },
    // 组件消亡
    surveyDestroy() {
      ko.components.unregister('svc-tab-template');
      RendererFactory.Instance.unregisterRenderer('dropdown', 'dropdown-vue');
      creator.onPropertyGridSurveyCreated.clear();
      creator.onSurveyPropertyValueChanged.clear();
      creator.onElementDeleting.clear();
    },
    // 选择logic类型时的处理逻辑
    selectChangeHandle() {
      this.formData.logic = undefined;
    },
    // 选择答案的处理逻辑
    checkboxChangeHandle(checkArr, e) {
      const allCheckArr = this.questionValue.map((i) => i.value).filter((i) => !['all', 'none', 'other'].includes(i));

      if (e.current === 'all') {
        if (checkArr.includes('all')) {
          this.formData.logic = [...allCheckArr, 'all'];
        } else {
          this.formData.logic = [];
        }
      } else if (e.current === 'none') {
        if (checkArr.includes('none')) {
          this.formData.logic = ['none'];
        }
      } else if (e === 'isCheckAll') {
        if (
          !checkArr.includes('all') &&
          this.formData.logic.sort().toString().includes(allCheckArr.sort().toString())
        ) {
          this.formData.logic.push('all');
        }
      } else {
        const contains = e.current !== 'other' && checkArr.includes('all') ? ['none', 'all'] : ['none'];
        this.formData.logic = this.formData.logic.filter((i) => !contains.includes(i));
        if (
          !checkArr.includes('all') &&
          this.formData.logic.sort().toString().includes(allCheckArr.sort().toString())
        ) {
          this.formData.logic.push('all');
        }
      }

      this.formData.logic.sort();
    },
    // dialog确定时添加数据
    handleOnConfirm(data) {
      if (!this.formData.name) {
        this.$message.error('风险名称不能为空');
        return;
      }
      this.$refs.form.validate().then((res) => {
        if (res === true) {
          const riskData = JSON.parse(JSON.stringify(data));
          const riskBody = document.querySelector('.risk-tbody');
          const riskArr = this.risk[this.questionName];

          // 数据处理
          riskData.file = this.files
            .filter((i) => i.status === 'success')
            .map((i) => i.path)
            .join(',');
          if (this.questionType === 'listbox' && riskData.logic instanceof Array) {
            const index = riskData.logic.indexOf('all');
            if (index > -1) {
              riskData.logic.splice(index, 1);
            }
          }

          // 当前为新增风险
          if (this.editIndex === -1) {
            if (riskArr.length === 0) riskBody.innerHTML = '';
            riskBody.appendChild(this.renderTrTemplate(riskData, riskArr.length));
            riskArr.push(riskData);
          }
          // 当前为修改风险
          if (this.editIndex > -1) {
            const deleteTr = document.querySelector(`.risk-tbody .risk-tr__${this.editIndex}`);
            riskBody.replaceChild(this.renderTrTemplate(riskData, this.editIndex), deleteTr);
            riskArr.splice(this.editIndex, 1, riskData);
          }
          this.dialogVisible = false;
          this.handleOnClose();
        }
      });
    },
    // dialog关闭时重置表单
    handleOnClose() {
      this.$refs.form.reset();
      this.formData.name = '风险名称';
      this.formData.logic = undefined;
      this.formData.logicType = LOGIC_TYPE_STATUS.EQUALS;
      this.files = [];
    },
    // 新增一行的操作
    handleOnAdd() {
      this.editIndex = -1;
      this.dialogVisible = true;
    },
    // 修改一行的操作
    handleOnEdit(index) {
      this.editIndex = index;
      const riskData = this.risk[this.questionName][index];
      this.formData = JSON.parse(JSON.stringify(riskData));
      if (this.formData.file) {
        this.files = this.formData.file
          ?.split(',')
          .map((path) => {
            if (!path) return;
            const name = path.split('/').pop();
            const size = name?.match(/\d+\./g).pop();
            return {
              name,
              status: 'success',
              url: FILE_URL_PREFIX + path,
              size,
              path,
            };
          })
          .filter((i) => i);
      }
      if (this.questionType === 'listbox' && this.formData.logic instanceof Array) {
        this.checkboxChangeHandle(this.formData.logic, 'isCheckAll');
      }
      if (!this.formData.logicType) this.formData.logicType = LOGIC_TYPE_STATUS.EQUALS;
      this.formData.level = Number(this.formData.level);
      this.dialogVisible = true;
    },
    // 删除一行的操作
    handleOnDelete(index) {
      const dialog = DialogPlugin.confirm({
        theme: 'warning',
        header: '警告',
        body: '再次确认是否删除风险？',
        onConfirm: () => {
          const riskArr = this.risk[this.questionName];
          riskArr.splice(index, 1);
          this.renderTable();
          dialog.destroy();
        },
      });
    },
    // 渲染整个表格
    renderTable() {
      const riskArr = this.risk[this.questionName];
      const riskBody = document.querySelector('.risk-tbody');
      if (!riskBody) return;
      if (!riskArr || riskArr.length === 0) {
        riskBody.innerHTML = `
           <div class="spg-matrixdynamic__placeholder">
            <div class="spg-matrixdynamic__placeholder-text">
              <span class="sv-string-viewer">还没有添加任何选项</span>
            </div>
            <button class="spg-btn spg-matrixdynamic__add-btn spg-action-button spg-action-button--large" onclick="handleOnAdd()">
              <span class="sv-string-viewer">添加一个选项</span>
            </button>
          </div>
        `;
        return;
      }

      riskBody.innerHTML = '';
      for (let i = 0; i < riskArr.length; i++) {
        riskBody.appendChild(this.renderTrTemplate(riskArr[i], i));
      }
    },
    // 渲染表格一行的模板
    renderTrTemplate({ name, level }, index) {
      const tr = document.createElement('tr');
      const { label, backgroundColor } = riskOptions[level];
      tr.className = `sd-table__row risk-tr__${index}`;
      tr.innerHTML = `
        <td class="spg-table__cell spg-table__cell--actions" style="height: 48px">
          <svg class="spg-drag-element__svg">
            <use xlink:href="#icon-drag-area-indicator"></use>
          </svg>
        </td>
        <td class="spg-table__cell sd-question--answered">
          <div class="sd-table__question-wrapper" style="width: 125.75px; color: #000;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
            <span style="font-size: calc(2 * var(--base-unit, 8px));">${name}</span>
          </div>
        </td>
        <td class="spg-table__cell sd-question--answered">
          <div class="sd-table__question-wrapper" style="text-align:center;width: 125.75px">
            <span style="font-size: calc(2 * var(--base-unit, 8px)); color: ${backgroundColor};">${label}</span>
          </div>
        </td>
        <td class="spg-table__cell spg-table__cell--actions">
          <div class="spg-action-bar">
            <div class="sv-action">
              <div class="sv-action__content">
                <button class="spg-action-button spg-action-button--icon spg-action-button--muted" onclick="handleOnEdit(${index})">
                  <svg class="sv-svg-icon spg-action-button__icon" aria-label="编辑" style="width: 24px; height: 24px;">
                    <use xlink:href="#icon-edit"></use>
                    <title>编辑</title>
                  </svg>
                </button>
              </div>
            </div>
            <div class="sv-action">
              <div class="sv-action__content">
                <button class="spg-action-button spg-action-button--icon spg-action-button--danger spg-action-button--muted" onclick="handleOnDelete(${index})">
                  <svg class="sv-svg-icon spg-action-button__icon" aria-label="删除" style="width: 24px; height: 24px;">
                    <use xlink:href="#icon-delete"></use>
                    <title>删除</title>
                  </svg>
                </button>
              </div>
            </div>
          </div>
        </td>
      `;
      return tr;
    },
    // 更改surveyjs json
    changeSurveyText(text) {
      creator.changeText(text);
    },
  },
};
</script>

<style lang="less" scoped>
#surveyCreator {
  height: 100vh;
}
.risk-form {
  padding: 20px 0;
  overflow-x: hidden;
  .risk-discovery {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .title {
      font-weight: 600;
    }
    .risk-box {
      display: flex;
      padding: 2px;
      background: #f3f3f3;
      border-radius: 3px;
      // align-items: center;
      .risk-box__item {
        width: 86px;
        height: 28px;
        border-radius: 2px;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        color: rgba(0, 0, 0, 0.6);
        &.red {
          background: #f36d78;
          color: rgba(255, 255, 255, 0.9);
        }
        &.green {
          background: #48c79c;
          color: rgba(255, 255, 255, 0.9);
        }
        &.blue {
          background: #0052d9;
          color: rgba(255, 255, 255, 0.9);
        }
      }
    }
  }
  /deep/ .t-form__label {
    // line-height: inherit;
    // white-space: wrap;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  /deep/ .t-space-item {
    border: 1px solid #e7e7e7;
    border-radius: 6px;
    padding: 16px 16px 24px;
  }
  /deep/ .t-radio-group {
    background-color: rgba(0, 0, 0, 0);
    gap: 16px;
    .t-radio__label {
      display: inline;
      white-space: inherit;
    }
    &.level {
      gap: 0;
      width: 100%;
      padding: 4px;
      background: #f8f8f8;
      box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);
      border-radius: 100px;
      .t-radio-group__bg-block {
        display: none;
      }
      .t-radio-button {
        width: 25%;
        height: 32px;
        display: flex;
        justify-content: center;
        &:first-child {
          border-radius: 40px 0px 0px 40px;
        }
        &:nth-child(4) {
          border-radius: 0px 40px 40px 0px;
        }
        // opacity: 0.5;
        // &.t-is-checked {
        //   opacity: 1;
        // }
        .t-radio-button__label {
          color: #fff;
        }
      }
    }
  }
  /deep/ .t-checkbox-group {
    .t-checkbox__label {
      display: inline;
      white-space: inherit;
      width: fit-content;
    }
  }
}
</style>
